import { Box3, BufferGeometry, Mesh, Object3D, Texture, Vector3 } from "three";

export default class MeshUtil {

    public static dispose(node) {
        if (!node) {
            return;
        }
        this.disposeNode(node);

        if (node.children) {
            let childrenArray = []; //node.children;
            node.children.forEach(element => {
                childrenArray.push(element)
            });

            for (let i = 0; i < childrenArray.length; i++) {
                let child = childrenArray[i];
                this.disposeHierarchy(child);
            }
        }


        //释放gpu缓存资源
        // App.getInstance().three.renderer.renderLists.dispose();
    }

    static disposeNode(node) {
        if (node instanceof Mesh) {
            if (node.geometry) {
                node.geometry.dispose();
            }

            if (node.material) {
                if (node.material.length > 1) {
                    let self = this;
                    node.material.forEach(element => {
                        self.disposeMaterial(element);
                    });
                } else {
                    this.disposeMaterial(node);
                    node.material.dispose();   // disposes any programs associated with the material
                }
            }

        }

        if (node.parent) {
            node.parent.remove(node);
        }
    }

    private static disposeMaterial(node) {
        if (node.material.map) node.material.map.dispose();
        if (node.material.lightMap) node.material.lightMap.dispose();
        if (node.material.bumpMap) node.material.bumpMap.dispose();
        if (node.material.normalMap) node.material.normalMap.dispose();
        if (node.material.specularMap) node.material.specularMap.dispose();
        if (node.material.envMap) node.material.envMap.dispose();
        if (node.material.alphaMap) node.material.alphaMap.dispose();
        if (node.material.aoMap) node.material.aoMap.dispose();
        if (node.material.displacementMap) node.material.displacementMap.dispose();
        if (node.material.emissiveMap) node.material.emissiveMap.dispose();
        if (node.material.gradientMap) node.material.gradientMap.dispose();
        if (node.material.metalnessMap) node.material.metalnessMap.dispose();
        if (node.material.roughnessMap) node.material.roughnessMap.dispose();

        //处理shadermaterial
        if (node.material['uniforms']) {
            for (const value of Object.values(node.material['uniforms'])) {
                if (value) {
                    const uniformValue = value['value'];
                    if (uniformValue instanceof Texture) {
                        uniformValue.dispose();
                    }
                    if (Array.isArray(uniformValue)) {
                        uniformValue.length = 0;
                    }
                }
            }
        }
    }

    /**
     * 释放节点资源。包括geometry和matrial
     * @param node 
     * @param callback 
     */
    static disposeHierarchy(node) {
        if (!node) {
            return;
        }
        this.disposeNode(node);

        // for (var i = node.children.length - 1; i >= 0; i--) {
        //   var child = node.children[i];
        //   this.disposeHierarchy(child, callback);
        //   callback(child);
        // }

        if (node.children) {
            let childrenArray = [];
            node.children.forEach(element => {
                childrenArray.push(element)
            });

            childrenArray.forEach(child => {
                this.disposeHierarchy(child);
                this.disposeNode(child);
            });
        }
    }

}
